package com.sjd.farm.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.sjd.common.constant.GoldenBeanConstants;
import com.sjd.common.core.domain.AjaxResult;
import com.sjd.common.utils.OrderNoUtils;
import com.sjd.farm.domain.SjdFarmGoodsDO;
import com.sjd.farm.domain.SjdFarmOrderDO;
import com.sjd.farm.domain.dto.order.WxFarmOrderCreateRequestDTO;
import com.sjd.farm.domain.dto.order.WxFarmOrderCreateResponseDTO;
import com.sjd.farm.domain.dto.order.WxFarmOrderQryResponseDTO;
import com.sjd.farm.mapper.SjdFarmGoodsMapper;
import com.sjd.farm.mapper.SjdFarmOrderMapper;
import com.sjd.farm.service.ISjdFarmLandClaimOrderService;
import com.sjd.farm.service.SjdFarmGoodsService;
import com.sjd.farm.service.WxFarmOrderService;
import com.sjd.mall.domain.SjdGoodsDO;
import com.sjd.mall.domain.SjdGoodsTypeDO;
import com.sjd.mall.domain.dto.base.OrderNoRequestDTO;
import com.sjd.mall.enums.GoodsClass;
import com.sjd.mall.enums.OrderStatus;
import com.sjd.mall.service.account.AccountGoldenBeanService;
import com.sjd.wx.utils.ThirdSessionHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;

/**
 * WxFarmOrderServiceImpl
 *
 * @author seer
 * @version 1.0
 * @date 2022/1/28 14:56
 */
@Service
@Slf4j
public class WxFarmOrderServiceImpl implements WxFarmOrderService {

    @Autowired
    private SjdFarmOrderMapper orderMapper;

    @Autowired
    private SjdFarmGoodsMapper goodsMapper;

    @Autowired
    private AccountGoldenBeanService accountService;

    @Autowired
    private ISjdFarmLandClaimOrderService landClaimOrderService;

    @Autowired
    private SjdFarmGoodsService goodsService;

    /**
     * 订单创建
     *
     * @return object
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult create(WxFarmOrderCreateRequestDTO requestDTO) {
        // 判断购买等级
        SjdFarmGoodsDO goods = goodsMapper.selectByPrimaryKey(requestDTO.getGoodsId());
        Assert.notNull(goods, "商品不存在 " + requestDTO.getGoodsId());
        int memLandLv = landClaimOrderService.getMaxLandLevelByMemberId(ThirdSessionHolder.getSjdMemberId());
        if (memLandLv < goods.getGoodsLevel()) {
            AjaxResult.error("土地等级不足");
        }
        // 减少库存
        MutablePair<Boolean, String> result = goodsService.decreaseStorage(requestDTO.getGoodsId(), requestDTO.getGoodsQuantity());
        if (!result.getLeft()) {
            log.warn("创建订单异常，扣减存库失败 {} {} {}", requestDTO.getGoodsId(), requestDTO.getGoodsQuantity(), result.getRight());
            return AjaxResult.error("商品库存不足");
        }
        String orderNo = OrderNoUtils.generateOrderNo(OrderNoUtils.OrderType.FARM_CONSUME);
        log.info("创建订单，生成订单号 {}", orderNo);
        BigDecimal orderAmount = goods.getGoodsPrice().multiply(requestDTO.getGoodsQuantity());
        LocalDateTime paymentDeadline = LocalDateTimeUtil.offset(LocalDateTime.now(), 2, ChronoUnit.HOURS);
        String clazz = GoodsClass.FARM_TOOLS == goods.getGoodsTypeClass() ? "农具" : "种子";
        JSONObject ast = new JSONObject();
        ast.put("name", goods.getGoodsName());
        ast.put("type", clazz);
        SjdFarmOrderDO order = new SjdFarmOrderDO();
        order.setGoodsClass(goods.getGoodsTypeClass());
        order.setOrderNo(orderNo);
        order.setOrderStatus(OrderStatus.CREATE_SUCCESS.value);
        order.setOrderStatusTime(LocalDateTime.now());
        order.setMemberId(ThirdSessionHolder.getSjdMemberId());
        order.setMemberMobile(ThirdSessionHolder.getThirdSession().getMobile());
        order.setOrderAmount(orderAmount);
        order.setOrderTime(LocalDateTime.now());
        order.setDiscountAmount(BigDecimal.ZERO);
        order.setPayableAmount(orderAmount);
        order.setPaymentDeadline(paymentDeadline);
        order.setPaymentAmount(orderAmount);
        order.setIsCanRefund(0);
        order.setGoodsId(goods.getGoodsId());
        order.setGoodsName(goods.getGoodsName());
        order.setGoodsPicture(goods.getBigPicture());
        order.setGoodsQuantity(requestDTO.getGoodsQuantity());
        order.setGoodsPrice(goods.getGoodsPrice());
        order.setGoodsAbstract(ast.toJSONString());
        orderMapper.insert(order);

        WxFarmOrderCreateResponseDTO response = new WxFarmOrderCreateResponseDTO();
        response.setId(order.getId());
        response.setOrderNo(order.getOrderNo());
        response.setOrderStatus(OrderStatus.CREATE_SUCCESS.value);
        response.setOrderStatusLabel(OrderStatus.CREATE_SUCCESS.label);
        response.setOrderAmount(order.getOrderAmount());
        response.setOrderTime(order.getOrderTime());
        response.setDiscountAmount(order.getDiscountAmount());
        response.setPaymentDeadline(order.getPaymentDeadline());
        response.setPayableAmount(order.getPayableAmount());
        response.setGoodsId(order.getGoodsId());
        response.setGoodsQuantity(order.getGoodsQuantity());
        response.setGoodsName(order.getGoodsName());
        response.setGoodsPicture(order.getGoodsPicture());
        response.setGoodsPrice(order.getGoodsPrice());
        return AjaxResult.success(response);
    }

    /**
     * 订单支付
     *
     * @param requestDTO requestDTO
     * @return object
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult pay(OrderNoRequestDTO requestDTO) {
        SjdFarmOrderDO orderDO = orderMapper.getByOrderNo(requestDTO.getOrderNo());
        Assert.notNull(orderDO, "订单不存在 " + requestDTO.getOrderNo());
        if (!OrderStatus.CREATE_SUCCESS.value.equals(orderDO.getOrderStatus())) {
            return AjaxResult.error("订单状态异常,禁止支付");
        }
        boolean timeout = orderDO.getPaymentDeadline().compareTo(LocalDateTime.now()) < 0;
        if (timeout) {
            return AjaxResult.error("订单超时,禁止支付");
        }
        // 金豆支付
        String orderType = GoodsClass.FARM_TOOLS == orderDO.getGoodsClass() ? GoldenBeanConstants.CONSUME_FARM_TOOLS : GoldenBeanConstants.CONSUME_SEED;
        String remark = "农场订单：" + orderDO.getOrderNo();
        AjaxResult result = accountService.createConsumeOrRefoundOrder(orderType, orderDO.getPayableAmount().intValue(), remark);
        if (!result.isSuccess()) {
            log.warn("订单支付失败 {}", result.get(AjaxResult.MSG_TAG));
            return result;
        }
        SjdFarmOrderDO update = new SjdFarmOrderDO();
        update.setOrderStatus(OrderStatus.PAY_SUCCESS.value);
        update.setOrderStatusTime(LocalDateTime.now());
        update.setPaymentAmount(orderDO.getPayableAmount());
        update.setPaymentTime(LocalDateTime.now());
        update.setOrderNo(orderDO.getOrderNo());
        orderMapper.updateSelectiveByOrderNo(update);
        return AjaxResult.success();
    }

    /**
     * 订单查询
     *
     * @return object
     */
    @Override
    public List<WxFarmOrderQryResponseDTO> qry() {
        List<SjdFarmOrderDO> resultList = orderMapper.listByMember(ThirdSessionHolder.getSjdMemberId());
        List<WxFarmOrderQryResponseDTO> respList = new ArrayList<>();
        for (SjdFarmOrderDO order : resultList) {
            WxFarmOrderQryResponseDTO response = new WxFarmOrderQryResponseDTO();
            response.setId(order.getId());
            response.setOrderNo(order.getOrderNo());
            response.setOrderStatus(order.getOrderStatus());
            response.setOrderStatusLabel(OrderStatus.label(order.getOrderStatus()));
            response.setOrderAmount(order.getOrderAmount());
            response.setOrderTime(order.getOrderTime());
            response.setDiscountAmount(order.getDiscountAmount());
            response.setPaymentAmount(order.getPaymentAmount());
            response.setPaymentTime(order.getPaymentTime());
            response.setReceiptTime(order.getReceiptTime());
            response.setGoodsId(order.getGoodsId());
            response.setGoodsId(order.getGoodsId());
            response.setGoodsQuantity(order.getGoodsQuantity());
            response.setGoodsName(order.getGoodsName());
            response.setGoodsPicture(order.getGoodsPicture());
            response.setGoodsPrice(order.getGoodsPrice());
            respList.add(response);
        }
        return respList;
    }

    /**
     * 订单自动取消,定时任务
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelQuartz() {
        // 查询2h内 订单创建订单
        LocalDateTime startTime = LocalDateTimeUtil.offset(LocalDateTime.now(), -2, ChronoUnit.HOURS);
        List<SjdFarmOrderDO> orderList = orderMapper.listCreate(startTime);
        for (SjdFarmOrderDO orderDO : orderList) {
            log.info("订单支付超时(2h),自动取消 {}", orderDO.getOrderNo());
            SjdFarmOrderDO update = new SjdFarmOrderDO();
            update.setOrderStatus(OrderStatus.CANCEL_SUCCESS.value);
            update.setOrderStatusTime(LocalDateTime.now());
            update.setCancelTime(LocalDateTime.now());
            update.setOrderNo(orderDO.getOrderNo());
            orderMapper.updateSelectiveByOrderNo(update);
            // 增加库存
            goodsService.increaseStorage(orderDO.getGoodsId(), orderDO.getGoodsQuantity());
            log.info("订单支付超时(2h),取消成功");
        }
    }

    /**
     * 获取所有的分类
     *
     * @param goods goods
     * @return object
     */
    private String getGoodsAbstract(SjdFarmGoodsDO goods) {
        String clazz = GoodsClass.FARM_TOOLS == goods.getGoodsTypeClass() ? "农具" : "种子";
        JSONObject obj = new JSONObject();
        obj.put("name", goods.getGoodsName());
        obj.put("type", clazz);
        return obj.toJSONString();
    }
}
